package com.stropheware.droidDefense;

import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;

import android.content.Context;
import android.graphics.Canvas;
import android.util.Log;

import com.stropheware.pathfinding.Path;
import com.stropheware.pathfinding.Path.Step;

public class EnemyManager {
	
	public static final int NUM_WAVES_PER_ROUND = 3;
	public static final int WAVE_SIZE = 3;
	public static final int TOTAL_SIZE = NUM_WAVES_PER_ROUND * WAVE_SIZE;
	public static final int NUM_TYPES_OF_ENEMIES = 4;
	
	private static final int WAVE_DELAY_MS = 8 * 1000;
	
	private static final String TAG = "EnemyManager";
	
	private BalancedEnemy [] balancedEnemies = new BalancedEnemy[NUM_WAVES_PER_ROUND * WAVE_SIZE];
	private FastEnemy [] fastEnemies = new FastEnemy[NUM_WAVES_PER_ROUND * WAVE_SIZE];
	private SlowEnemy [] slowEnemies = new SlowEnemy[NUM_WAVES_PER_ROUND * WAVE_SIZE];
	private BalancedEnemy [] bossEnemy = new BalancedEnemy[1];
	public AbstractEnemy [][] enemyArray = new AbstractEnemy[NUM_TYPES_OF_ENEMIES][];
	
	public Path globalPath;
	public int activeEnemy = 0;
	public int waveNum = 0;
	public int waveDelaySeconds = 3;
	public int activeEnemiesInRound;
	private GameBoard gameBoard;
	private Context context;
	private GameThread gameThread;
	public GameManager gameManager;
	private Timer waveTimer = new Timer();
	private Timer bufferTimer = new Timer();
	
	public EnemyManager(GameManager gameManager){
		this.gameBoard = gameManager.gameBoard;
		this.context = gameManager.context;
		this.gameThread = gameManager.gameThread;
		this.gameManager = gameManager;
		for(int j = 0; j < TOTAL_SIZE; j++) {
			balancedEnemies[j] = new BalancedEnemy(context, gameBoard, this, j);
			fastEnemies[j] = new FastEnemy(context, gameBoard, this, j);
			slowEnemies[j] = new SlowEnemy(context, gameBoard, this, j);
		}
		bossEnemy[0] = new BalancedEnemy(context, gameBoard, this, 0);
		enemyArray[0] = balancedEnemies;
		enemyArray[1] = fastEnemies;
		enemyArray[2] = slowEnemies;
		enemyArray[3] = bossEnemy;
	}
	

	public void updatePath(Path newPath) {
		this.globalPath = newPath;
		for(int i = 0; i < NUM_TYPES_OF_ENEMIES; i++)
			for(int j = 0; j < enemyArray[i].length; j++) {
				if(!enemyArray[i][j].visible) enemyArray[i][j].updatePath(newPath.steps);
		} 
	}
	
	public ArrayList<AbstractEnemy> getActiveEnemies() {
		ArrayList<AbstractEnemy> activeEnemies = new ArrayList<AbstractEnemy>();
		for(int j = 0; j < enemyArray[activeEnemy].length; j++) {
			if(enemyArray[activeEnemy][j].visible == true) activeEnemies.add(enemyArray[activeEnemy][j]);
		}
		return activeEnemies;
	}
	
	private void launchWave() {
		//sort of hack with boss wave, but w/e
		for(int i = waveNum * WAVE_SIZE; i < enemyArray[activeEnemy].length; i++) {
			enemyArray[activeEnemy][i].reset(i - (waveNum * WAVE_SIZE)); 
		}
		Log.d(TAG, "launching wave of " + activeEnemy + " 0 = med, 1 = fast, 2 = slow 3 = BOSS");
		waveNum++;
		if(waveNum == WAVE_SIZE) waveNum = 0;
	}
	
	public void enemyCompletedGoal() {
		gameManager.lifeLost();
		activeEnemiesInRound--;
		if(activeEnemiesInRound <= 0) gameManager.roundCompleted();
	}
	
	public void enemyKilled(AbstractEnemy enemy) {
		gameManager.enemyKilled(enemy);
		activeEnemiesInRound--;
		Log.d(TAG, "activeEnemiesinRound:" + activeEnemiesInRound);
		if(activeEnemiesInRound <= 0) gameManager.roundCompleted();
	}
	
	public void update(int tickCounter) {
		for(int j = 0; j < enemyArray[activeEnemy].length; j++) {
			enemyArray[activeEnemy][j].update(tickCounter);
		}
		if(tickCounter % enemyArray[activeEnemy][0].speed == 0) gameManager.towerManager.evaluateTargets();
	}
	
	public void draw(Canvas canvas) {
		for(int j = 0; j < enemyArray[activeEnemy].length; j++) {
			enemyArray[activeEnemy][j].drawDrawable(canvas);
		}
	}
	
	public AbstractEnemy[] getActiveEnemyArray() {
		return enemyArray[activeEnemy];
	}
	
	/**
	 * used for bomb like object.. last resort kills all enemies
	 */
	public void killAllActiveEnemies() {
		for(int i = 0; i < enemyArray[activeEnemy].length; i++) {
			enemyArray[activeEnemy][i].hit(enemyArray[activeEnemy][i].health);
		}
	}
	
	public void accelShaken() {
		Log.d(TAG, "round starting");
		activeEnemiesInRound = enemyArray[activeEnemy].length;
		launchWave();
		waveTimer.schedule(new WaveTask(), WAVE_DELAY_MS);
		waveTimer.schedule(new WaveTask(), 2 * WAVE_DELAY_MS);	
	}
	
	public void changeActiveEnemy(){
		if(++activeEnemy == NUM_TYPES_OF_ENEMIES) activeEnemy = 0;
	}
	
	class WaveTask extends TimerTask {
		public void run() {
			launchWave();
		}
	}
}
